package com.uzai.console.service.wechatwork.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.common.enums.DeviceTypeEnum;
import com.uzai.common.enums.GroupSendStatusEnum;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.console.common.ResponseMsg;
import com.uzai.console.common.utils.DateUtil;
import com.uzai.console.common.utils.Tools;
import com.uzai.console.common.utils.ZipUtils;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.constant.Const;
import com.uzai.console.constant.ES.ESConstant;
import com.uzai.console.dto.wechatwork.wxworkcontacts.WxworkContactsQuery;
import com.uzai.console.dto.wechatwork.wxworkcontacts.WxworkExportResultDto;
import com.uzai.console.dto.wechatwork.wxworkcontacts.WxworkNewBatchSendMessageTaskDto;
import com.uzai.console.entity.DeviceWechatInfo;
import com.uzai.console.entity.DeviceWxworkInfo;
import com.uzai.console.entity.GroupSendJob;
import com.uzai.console.entity.Merchant;
import com.uzai.console.enums.ExportInfoTypeEnum;
import com.uzai.console.enums.GroupSendJobSourceEnum;
import com.uzai.console.enums.SmsType;
import com.uzai.console.mapper.DeviceWxworkInfoMapper;
import com.uzai.console.mapper.GroupSendJobMapper;
import com.uzai.console.mapper.MerchantMapper;
import com.uzai.console.service.exportinfo.ExportInfoService;
import com.uzai.console.service.wechatwork.WxworkContactsGroupSendMsgService;
import com.uzai.console.service.wechatwork.WxworkContactsService;
import com.uzai.console.service.wechatwork.WxworkContactsSyncService;
import com.uzai.console.vo.exportinfo.ExportAmountVo;
import com.uzai.console.vo.wechatprivate.wxcontacts.WxContactsExport;
import com.uzai.console.vo.wechatprivate.wxcontacts.WxContactsInfoVo;
import com.uzai.console.vo.wechatwork.wxworkcontacts.WxworkContactsExport;
import com.uzai.console.vo.wechatwork.wxworkcontacts.WxworkContactsVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 企业微信-企业微信通讯录
 * @author liuqi
 * @date 2021年08月13日 11:34
 */
@Service
public class WxworkContactsGroupSendMsgServiceImpl implements WxworkContactsGroupSendMsgService {

    Logger logger = LoggerFactory.getLogger(WxworkContactsGroupSendMsgServiceImpl.class);

    @Autowired
    private GroupSendJobMapper groupSendJobMapper;
    @Autowired
    private WxworkContactsSyncService wxworkContactsSyncService;
    @Autowired
    private WxworkContactsService wxworkContactsService;
    @Autowired
    private ExportInfoService exportInfoService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private DeviceWxworkInfoMapper deviceWxworkInfoMapper;
    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;


    /**
     * 新建群发任务
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param wxworkNewBatchSendMessageTaskDto
     * @return null
     */
    public void newBatchSendMessageTask(WxworkNewBatchSendMessageTaskDto wxworkNewBatchSendMessageTaskDto, String loginName){

//        if(true){
//            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "活动期间，禁止群发功能");
//        }

        if(wxworkNewBatchSendMessageTaskDto.getMerId() == null ){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAM_ERROR);
        }

        List<Long> deviceUniqueIdList = wxworkNewBatchSendMessageTaskDto.getDeviceUniqueIdList();
        if(deviceUniqueIdList == null || deviceUniqueIdList.size() == 0){ //
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请选择发送消息的机器人");
        }

        if(StringUtils.isBlank(wxworkNewBatchSendMessageTaskDto.getName())){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入任务名称");
        }

        if(wxworkNewBatchSendMessageTaskDto.getTimeInterval() == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入发送时间间隔");
        }

        if(StringUtils.isBlank(wxworkNewBatchSendMessageTaskDto.getContent())){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入消息内容");
        }

        if(wxworkNewBatchSendMessageTaskDto.getBeginTime() == null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入发送时间");
        }

        WxworkContactsQuery wxworkContactsQuery = new WxworkContactsQuery();
        wxworkContactsQuery.setMerId(wxworkNewBatchSendMessageTaskDto.getMerId());
        wxworkContactsQuery.setSubDeviceUniqueIdList(wxworkNewBatchSendMessageTaskDto.getSubDeviceUniqueIdList());

        //免打扰时间
        Integer busyTimeInterval = wxworkNewBatchSendMessageTaskDto.getBusyTimeInterval();
        //页面设置了免打扰时间(页面填写的是天数)
        if(busyTimeInterval != null){
            //免骚扰时间(针对群发消息用户过滤，这个时间发以后已经群发消息的用户不查询出来) = 现在时间-页面设置的免打扰时间
            Integer busyGroupSendMsgTime = wxworkNewBatchSendMessageTaskDto.getBeginTime() - busyTimeInterval * 3600 ;
            wxworkContactsQuery.setBusyGroupSendMsgTime(busyGroupSendMsgTime);
        }

        //发送消息总数
        long totalCount = 0;

        for (Long deviceUniqueId : deviceUniqueIdList) {
            wxworkContactsQuery.setDeviceUniqueId(deviceUniqueId);
            //单个机器人查询总数
            long totalCount_device = wxworkContactsService.searchTotal(wxworkContactsQuery);
            if(totalCount_device >= ESConstant.TOTAL_MAX) { //大于2万条，不支持群发
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该机器人下的通讯录成员总数超过2万个，机器人id=：" + deviceUniqueId);
            }
            totalCount = totalCount + totalCount_device;
        }

        //发送消息总数
        if(totalCount == 0){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "选择的机器人没有通讯录好友");
        }

        Integer now = DateUtil.getNowTime();
        //添加群发消息主任务
        GroupSendJob groupSendJobParent = new GroupSendJob();
        groupSendJobParent.setId(IdWorker.getId());
        groupSendJobParent.setParentId(0L); //主任务
        groupSendJobParent.setMerId(wxworkNewBatchSendMessageTaskDto.getMerId());
        groupSendJobParent.setDeviceType(DeviceTypeEnum.DT_WORK_WECHAT.getKey());
        //任务名称
        String name = Tools.getStr(wxworkNewBatchSendMessageTaskDto.getName());
        name = name
                .replace("[创建时间]", Tools.getDateFormat(new Date(now * 1000L), "yyMMdd"))
                .replace("[创建账号]", Tools.getStr(loginName));

        if(deviceUniqueIdList.size() == 1){//需要过滤参数
            DeviceWxworkInfo deviceWxworkInfo = deviceWxworkInfoMapper.selectById(deviceUniqueIdList.get(0), wxworkNewBatchSendMessageTaskDto.getMerId());
            if(deviceWxworkInfo == null){
                throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "选择的机器人不存在");
            }
            name = name.replace("[机器人昵称]", Tools.getStr(deviceWxworkInfo.getDeviceName()))
                    .replace("[机器人备注]",Tools.getStr(deviceWxworkInfo.getDeviceRemark()));
        }
        groupSendJobParent.setName(name);
        groupSendJobParent.setSource(GroupSendJobSourceEnum.WORK_CONTACTS.getId());
        groupSendJobParent.setContent(wxworkNewBatchSendMessageTaskDto.getContent());
        groupSendJobParent.setStatus(GroupSendStatusEnum.INIT.getValue());
        //groupSendJobParent.setTotalCount((int)totalCount); //预计发送总数
        groupSendJobParent.setTotalCount(0); //默认预计发送总数为0
        groupSendJobParent.setFinishCount(0);
        groupSendJobParent.setTimeIntervalMin(wxworkNewBatchSendMessageTaskDto.getTimeIntervalMin());
        groupSendJobParent.setTimeInterval(wxworkNewBatchSendMessageTaskDto.getTimeInterval());
        groupSendJobParent.setBeginTime(wxworkNewBatchSendMessageTaskDto.getBeginTime());
        groupSendJobParent.setEndTime(wxworkNewBatchSendMessageTaskDto.getEndTime());
        groupSendJobParent.setExptime(now + 15*24*3600); //当前时间之后的15天内
        groupSendJobParent.setUserRemark(wxworkNewBatchSendMessageTaskDto.getUserRemark());
        groupSendJobParent.setUserLab(Tools.getStrNull(JSONObject.toJSONString(wxworkNewBatchSendMessageTaskDto.getUserLabList())));
        groupSendJobParent.setCleanLab(wxworkNewBatchSendMessageTaskDto.getCleanLab());
        //会员标签
        groupSendJobParent.setUserTags(Tools.getStrNull(JSONObject.toJSONString(wxworkNewBatchSendMessageTaskDto.getUserTagsList())));
        groupSendJobParent.setNightTime(wxworkNewBatchSendMessageTaskDto.getNightTime());
        groupSendJobParent.setCreateTime(now);
        groupSendJobParent.setUpdateTime(now);
        groupSendJobParent.setBusyTimeInterval(wxworkNewBatchSendMessageTaskDto.getBusyTimeInterval());
        groupSendJobParent.setIgnoreName(Tools.getStrEmpty(JSONObject.toJSONString(wxworkNewBatchSendMessageTaskDto.getIgnoreNameList())));
        groupSendJobParent.setIgnoreRemark(Tools.getStrEmpty(JSONObject.toJSONString(wxworkNewBatchSendMessageTaskDto.getIgnoreRemarkList())));
        groupSendJobParent.setSendStartTime(wxworkNewBatchSendMessageTaskDto.getBeginTime());
        groupSendJobParent.setUserQueryPara(Tools.getStrNull(JSONObject.toJSONString(wxworkNewBatchSendMessageTaskDto.getGroupSendJobUserQueryParaDto())));
        groupSendJobParent.setParaQueryType(Tools.getInteger(wxworkNewBatchSendMessageTaskDto.getParaQueryType()));
        groupSendJobMapper.insertSelective(groupSendJobParent);

        //后台异步线程创建子任务和群发消息
        wxworkContactsSyncService.newBatchSendMessageTaskSync(wxworkNewBatchSendMessageTaskDto, groupSendJobParent.getId(), loginName);

    }

    /**
     * 查询通讯结果导出数据
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param wxworkExportResultDto
     * @return null
     */
    public void exportByQeuryResult(WxworkExportResultDto wxworkExportResultDto){

        if(wxworkExportResultDto.getMerId() == null ){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAM_ERROR);
        }

        if(StringUtils.isBlank(wxworkExportResultDto.getCode())){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请输入验证码");
        }

        Merchant merchant = merchantMapper.selectById(wxworkExportResultDto.getMerId());
        if(merchant == null ){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "运营商不存在");
        }

        //获取存在redis中的验证码
        //如果输入的验证码不是系统通用密码，则需要验证
        if(!uzaiConsoleSysConfig.getDefaultPassword().equals(wxworkExportResultDto.getCode())) {
            String codeByRedis = (String) redisTemplate.opsForValue().get(String.format(SmsType.SPECIAL_OPERATE.getDesc(), merchant.getMobile()));
            //判断验证码是否过期
            if (StringUtils.isBlank(codeByRedis)) {
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.CODE_MISS);
            }

            //验证码是否正确
            if (!codeByRedis.equals(wxworkExportResultDto.getCode())) {
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.CODE_ERR);
            }
        }

        WxworkContactsQuery wxworkContactsQuery = wxworkExportResultDto.getWxworkContactsQuery();
        wxworkContactsQuery.setMerId(wxworkExportResultDto.getMerId());

        //机器人列表
        List<Long> deviceUniqueIdList = wxworkContactsQuery.getDeviceUniqueIdList();
        if(deviceUniqueIdList == null && deviceUniqueIdList.size() == 0){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "请选择机器人");
        }


        ExportAmountVo exportAmountVo = wxworkContactsService.getExportAmount(wxworkContactsQuery);

        //生成ZIP文件流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream out = new ZipOutputStream(outputStream);

        //查询总数
        for (Long deviceUniqueId : deviceUniqueIdList) {
            //导出excel文件序号
            long exportFileNumber = deviceUniqueId.longValue();
            //分页查询（每页10条）
            //执行分页查询对象
            wxworkContactsQuery.setSize(100);
            int currentPage = 1;
            wxworkContactsQuery.setCurrent(currentPage);
            wxworkContactsQuery.setDeviceUniqueIdList(null);
            wxworkContactsQuery.setDeviceUniqueId(deviceUniqueId);

            //存放导出文件对象(一万条一个表格)
            List<WxworkContactsExport> wxworkContactsExportList = new ArrayList<>();
            //查询通讯录
            Page<WxworkContactsVo> wxworkContactsVoList = wxworkContactsService.findWxworkContactsList(wxworkContactsQuery, false);
            while(wxworkContactsVoList != null && wxworkContactsVoList.getRecords() != null && wxworkContactsVoList.getRecords().size() > 0){
                for(WxworkContactsVo wxworkContactsVo : wxworkContactsVoList.getRecords()){
                    WxworkContactsExport wxworkContactsExport = new WxworkContactsExport();
                    BeanUtils.copyProperties(wxworkContactsVo, wxworkContactsExport);
                    wxworkContactsExportList.add(wxworkContactsExport);
                }

                //循环查询下一页
                currentPage ++ ;
                wxworkContactsQuery.setCurrent(currentPage);
                wxworkContactsVoList = wxworkContactsService.findWxworkContactsList(wxworkContactsQuery,false);
            }

            ByteArrayOutputStream byteArrayOutputStream = null;
            try {
                //导出的文件序号,每次导出+1
                String fileName = "企业微信通讯录_" + exportFileNumber +".xlsx";
                //创建流
                byteArrayOutputStream = new ByteArrayOutputStream();
                //打包成ZIP文件
                EasyExcel.write(byteArrayOutputStream, WxContactsExport.class).registerConverter(new LongStringConverter()).sheet("企业微信通讯录").doWrite(wxworkContactsExportList);
                ZipUtils.zip(out, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), fileName);
                byteArrayOutputStream.close();
                //清空本次导出的数据列表
                wxworkContactsExportList.clear();
            }catch (Exception e){
                if(byteArrayOutputStream != null){
                    try {
                        byteArrayOutputStream.close();
                    } catch (IOException ex) {
                        logger.error(ex.getMessage(), ex);
                    }
                }
                logger.error("----导出企业微信通讯录异常--error={}", e.getMessage());
            }

        }

        try {
            // 注意关闭流的顺序，在上传oss之前必须关闭流否则下载解压的时候会报“文件末端错误”的问题
            outputStream.close();
            out.close();
        }catch (Exception e){
            logger.error("----导出企业微信通讯录异常--error={}", e.getMessage());
        }finally {

        }

        InputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
        String zipFileName = "企业微信通讯录_" + System.currentTimeMillis() + ".zip";
        //上传文件通讯录
        exportInfoService.uploadExportFile(byteArrayInputStream, wxworkExportResultDto.getMerId(), zipFileName, exportAmountVo, ExportInfoTypeEnum.EXPORT_INFO_WXWORKCONTACTS.getId());

    }

}
